<template>
  <el-dialog v-model="dialogVisible" :title="parameter.title" width="680px" lock-scroll destroy-on-close draggable>
    <el-form ref="formRef" :model="parameter.menu" label-width="100px" label-suffix=" :">
      <el-tabs v-model="parameter.menu.menuType" tab-position="left">
        <!-- 目录 -->
        <el-tab-pane :name="0" label="目录">
          <el-form-item label="上级目录" prop="pid">
            <el-cascader
              v-model="parameter.menu.pid"
              :options="formInline.higherMenuOptions"
              :props="{ checkStrictly: true, emitPath: false }"
              style="width: 100%"
              clearable
              filterable
              placeholder="请选择上级目录"
            >
              <template #default="{ node, data }">
                <span>{{ data.label }}</span>
                <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
              </template>
            </el-cascader>
          </el-form-item>
          <el-form-item label="目录名称" prop="title" :rules="[{ required: true, message: '请输入目录名称', trigger: 'blur' }]">
            <el-input v-model="parameter.menu.title" placeholder="请填写目录名称" clearable />
          </el-form-item>
          <el-form-item label="路由名称" prop="name" :rules="[{ required: true, message: '请输入路由名称', trigger: 'blur' }]">
            <el-input v-model="parameter.menu.name" placeholder="请填写路由名称" clearable />
          </el-form-item>
          <el-form-item label="路由地址" prop="path">
            <el-input v-model="parameter.menu.path" placeholder="请填写路由地址" clearable />
          </el-form-item>
          <el-form-item label="重定向路由" prop="redirect">
            <el-input v-model="parameter.menu.redirect" placeholder="请填写重定向路由" clearable />
          </el-form-item>
          <el-form-item label="目录图标" prop="icon">
            <select-icon v-model:icon-value="parameter.menu.icon!" />
          </el-form-item>
          <el-form-item label="权重(排序)" prop="sort">
            <el-input-number v-model="parameter.menu.sort" :precision="0" :value-on-clear="0" :min="0" />
          </el-form-item>
        </el-tab-pane>
        <!-- 菜单 -->
        <el-tab-pane :name="1" label="菜单">
          <el-form-item label="上级菜单" prop="pid">
            <el-cascader
              v-model="parameter.menu.pid"
              :options="formInline.higherMenuOptions"
              :props="{ checkStrictly: true, emitPath: false }"
              style="width: 100%"
              clearable
              filterable
              placeholder="请选择上级菜单"
            >
              <template #default="{ node, data }">
                <span>{{ data.label }}</span>
                <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
              </template>
            </el-cascader>
          </el-form-item>
          <el-form-item label="菜单名称" prop="title" :rules="[{ required: true, message: '请输入菜单名称', trigger: 'blur' }]">
            <el-input v-model="parameter.menu.title" placeholder="请填写菜单名称" clearable />
          </el-form-item>
          <el-form-item label="路由名称" prop="name" :rules="[{ required: true, message: '请输入路由名称', trigger: 'blur' }]">
            <el-input v-model="parameter.menu.name" placeholder="请填写路由名称" clearable />
          </el-form-item>
          <el-form-item label="路由地址" prop="path">
            <el-input v-model="parameter.menu.path" placeholder="请填写路由地址" clearable />
          </el-form-item>
          <el-form-item label="组件路径" prop="component">
            <el-input v-model="parameter.menu.component" placeholder="请填写组件路径" clearable>
              <template #append>
                <el-select v-model="componentType" style="width: 80px">
                  <el-option label="组件" :value="0" />
                  <el-option label="外链" :value="1" />
                </el-select>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item prop="activeMenu">
            <template #label>
              <span style="display: inline-flex; align-items: center">
                <el-tooltip effect="dark" content="当菜单为详情页时,左侧菜单需要高亮的项" placement="top-start">
                  <el-icon style="margin-right: 4px"><InfoFilled /></el-icon>
                </el-tooltip>
                高亮菜单 :
              </span>
            </template>
            <el-input v-model="parameter.menu.activeMenu" placeholder="请填写高亮菜单" clearable />
          </el-form-item>
          <el-form-item prop="params">
            <template #label>
              <span style="display: inline-flex; align-items: center">
                <el-tooltip effect="dark" content="此参数会在跳转时拼接在Url中" placement="top-start">
                  <el-icon style="margin-right: 4px"><InfoFilled /></el-icon>
                </el-tooltip>
                路由参数 :
              </span>
            </template>
            <el-input v-model="parameter.menu.params" placeholder="请填写路由参数" clearable>
              <template #prepend>
                <el-select v-model="parameter.menu.splicingMethod" style="width: 95px">
                  <el-option label="query" :value="0" />
                  <el-option label="params" :value="1" />
                </el-select>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item label="权重(排序)" prop="sort">
            <el-input-number v-model="parameter.menu.sort" :precision="0" :value-on-clear="0" :min="0" />
          </el-form-item>
          <el-form-item label="扩展属性">
            <el-checkbox v-model="parameter.menu.isHide" name="isHide" label="隐藏菜单" border />
            <el-checkbox v-model="parameter.menu.isAffix" name="isAffix" label="固定tab" border />
            <el-checkbox v-model="parameter.menu.isKeepAlive" name="isKeepAlive" label="缓存组件" border />
          </el-form-item>
        </el-tab-pane>
        <!-- 按钮 -->
        <el-tab-pane :name="2" label="按钮">
          <el-form-item label="所属菜单" prop="pid">
            <el-cascader
              v-model="parameter.menu.pid"
              :options="formInline.higherMenuOptions"
              :props="{ checkStrictly: true, emitPath: false }"
              style="width: 100%"
              clearable
              filterable
              placeholder="请选择所属菜单"
            >
              <template #default="{ node, data }">
                <span>{{ data.label }}</span>
                <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
              </template>
            </el-cascader>
          </el-form-item>
          <el-form-item label="按钮名称" prop="title" :rules="[{ required: true, message: '请输入按钮名称', trigger: 'blur' }]">
            <el-input v-model="parameter.menu.title" placeholder="请填写按钮名称" clearable />
          </el-form-item>
          <el-form-item label="按钮编码" prop="name" :rules="[{ required: true, message: '请输入按钮编码', trigger: 'blur' }]">
            <el-input v-model="parameter.menu.name" placeholder="请填写按钮编码 (sys:menu:add)" clearable />
          </el-form-item>
        </el-tab-pane>
      </el-tabs>
    </el-form>
    <template #footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" @click="handleSubmit">提交</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts" name="menuEdit">
import type { ResultData, Option, SysMenu } from "@/api/interface";
import type { FormInstance } from "element-plus";
import { ref, reactive, watch } from "vue";
import { FormEnum } from "@/enums/formEnum";
import { getMenuCascaderOptionApi } from "@/api/modules/system/menu";
import { ElMessage } from "element-plus";
import SelectIcon from "@/components/SelectIcon/index.vue";

/** 系统菜单 */
interface EditProps {
  /** 标题 */
  title: string;
  /** 待编辑的菜单 */
  menu: Partial<SysMenu.Form>;
  /** 获取表格数据的Api */
  getTableList?: () => void;
  /** 提交表单的Api */
  submitApi?: (params: any) => Promise<ResultData<boolean>>;
}

/** 表单内联数据 */
interface FormInline {
  /** 上级菜单选项 */
  higherMenuOptions: Option.CascadeOption[];
}

/** 表单实例 */
const formRef = ref<FormInstance>();
/** dialog 状态 */
const dialogVisible = ref(false);
/** 组件类型 */
const componentType = ref(0);
/** 父组件传过来的参数 */
const parameter = ref<EditProps>({
  title: "",
  menu: {
    menuType: 0,
    sort: 0,
    icon: "",
    splicingMethod: 0
  }
});
/** 表单在线数据 */
const formInline = reactive<FormInline>({
  higherMenuOptions: []
});

/**
 * 接收父组件参数
 *
 * @param params 父组件传过来的参数
 * @returns void
 */
const acceptParams = (params: EditProps) => {
  parameter.value = params;
  // 处理 params.menu 中的 link 不为空时，设置 component 的这值为 link, 设置menuType 为 1
  if (parameter.value.menu.link) {
    parameter.value.menu.component = parameter.value.menu.link;
    componentType.value = 1;
  }

  dialogVisible.value = true;
};

/**
 * 初始化表单数据
 *
 * 1. 重置表单
 * 2. 获取上级菜单选项
 * 3. 加载表单数据
 *
 * @returns void
 */
const initFormInline = () => {
  formRef.value?.resetFields();
  formInline.higherMenuOptions = [];

  getMenuCascaderOptionApi().then(({ data }) => {
    formInline.higherMenuOptions = data;
  });
};

/**
 * 提交页面上的数据
 *
 * 1. 校验表单
 * 2. 表单数据处理
 * 3. 提交表单
 * 4. 提交结果处理
 * 5. 异常处理
 *
 * @returns void
 */
const handleSubmit = () => {
  formRef.value
    // 1. 校验表单
    ?.validate()
    // 2. 表单数据处理
    .then(() => {
      switch (parameter.value.menu.menuType) {
        case 0:
          componentType.value = 0;
          parameter.value.menu = {
            id: parameter.value.menu.id || FormEnum.EmptyId,
            pid: parameter.value.menu.pid || FormEnum.EmptyId,
            title: parameter.value.menu.title,
            name: parameter.value.menu.name,
            path: parameter.value.menu.path || `/${parameter.value.menu.name}`,
            redirect: parameter.value.menu.redirect || "",
            icon: parameter.value.menu.icon || "Menu",
            menuType: 0,
            sort: parameter.value.menu.sort || 0
          };
          break;
        case 1:
          parameter.value.menu = {
            id: parameter.value.menu.id || FormEnum.EmptyId,
            pid: parameter.value.menu.pid || FormEnum.EmptyId,
            title: parameter.value.menu.title,
            name: parameter.value.menu.name,
            path: parameter.value.menu.path || `/${parameter.value.menu.name}`,
            component: componentType.value != 1 ? parameter.value.menu.component || "" : "",
            link: componentType.value === 1 ? parameter.value.menu.component || "" : "",
            activeMenu: parameter.value.menu.activeMenu || "",
            params: parameter.value.menu.params || "",
            splicingMethod: parameter.value.menu.splicingMethod || 0,
            icon: "Menu",
            isHide: parameter.value.menu.isHide || false,
            isAffix: parameter.value.menu.isAffix || false,
            isKeepAlive: parameter.value.menu.isKeepAlive || false,
            menuType: 1,
            sort: parameter.value.menu.sort || 0
          };
          break;
        case 2:
          componentType.value = 0;
          parameter.value.menu = {
            id: parameter.value.menu.id || FormEnum.EmptyId,
            pid: parameter.value.menu.pid || FormEnum.EmptyId,
            title: parameter.value.menu.title,
            name: parameter.value.menu.name,
            menuType: 2,
            sort: 0
          };
          break;
      }
      return parameter.value.menu;
    })
    // 3. 提交表单
    .then(menu => {
      return parameter.value.submitApi!(menu);
    })
    // 4. 提交结果处理
    .then(({ data }) => {
      if (data) {
        ElMessage.success({ message: `${parameter.value.title}成功！` });
        parameter.value.getTableList!();
        dialogVisible.value = false;
      } else {
        ElMessage.error({ message: `${parameter.value.title}失败！` });
      }
    })
    // 5. 异常处理
    .catch((error: Error) => {
      if (error.message) ElMessage.error({ message: `${parameter.value.title}异常：${error.message}` });
      else ElMessage.error({ message: "请检查表单数据是否填写完整！" });
    });
};

// 监听 dialogVisible 的变化
watch(dialogVisible, val => {
  if (val) {
    initFormInline();
  }
});

// 暴露给父组件的属性和方法
defineExpose({
  acceptParams
});
</script>
